package com.tbynet.jwp.framework.kit;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Random;

/**
 * 数字处理工具类
 *
 * @author 佰亿互联
 * @version 3.1
 * @since 2025-11-04
 */
public class NumberKit {

    // ========== 数字验证方法 ==========

    /**
     * 验证数字是否为正数
     *
     * @param number 数字
     * @return 是否为正数
     *
     * @example
     * <pre>{@code
     * boolean result = NumberKit.isPositive(123);
     * // 返回 true
     * }</pre>
     */
    public static boolean isPositive(Number number) {
        return number != null && number.doubleValue() > 0;
    }

    /**
     * 验证数字是否为非负数
     *
     * @param number 数字
     * @return 是否为非负数
     *
     * @example
     * <pre>{@code
     * boolean result = NumberKit.isNonNegative(0);
     * // 返回 true
     * }</pre>
     */
    public static boolean isNonNegative(Number number) {
        return number != null && number.doubleValue() >= 0;
    }

    /**
     * 验证数字是否为负数
     *
     * @param number 数字
     * @return 是否为负数
     *
     * @example
     * <pre>{@code
     * boolean result = NumberKit.isNegative(-123);
     * // 返回 true
     * }</pre>
     */
    public static boolean isNegative(Number number) {
        return number != null && number.doubleValue() < 0;
    }

    /**
     * 验证数字是否在指定范围内
     *
     * @param number 数字
     * @param min 最小值
     * @param max 最大值
     * @return 是否在范围内
     *
     * @example
     * <pre>{@code
     * boolean result = NumberKit.isInRange(5, 1, 10);
     * // 返回 true
     * }</pre>
     */
    public static boolean isInRange(Number number, Number min, Number max) {
        if (number == null || min == null || max == null) {
            return false;
        }
        double value = number.doubleValue();
        return value >= min.doubleValue() && value <= max.doubleValue();
    }

    /**
     * 验证数字是否为整数（浮点数验证）
     *
     * @param number 数字
     * @return 是否为整数
     *
     * @example
     * <pre>{@code
     * boolean result = NumberKit.isIntegerValue(123.0);
     * // 返回 true
     * }</pre>
     */
    public static boolean isIntegerValue(Number number) {
        if (number == null) {
            return false;
        }
        return number.doubleValue() % 1 == 0;
    }

    // ========== 数字转换方法 ==========

    /**
     * 安全转换为整数（转换失败返回默认值）
     *
     * @param str 字符串
     * @param defaultValue 默认值
     * @return 整数
     *
     * @example
     * <pre>{@code
     * int result = NumberKit.safeParseInt("123", 0);
     * // 返回 123
     * }</pre>
     */
    public static Integer safeParseInt(String str, Integer defaultValue) {
        if (StringKit.isInteger(str)) {
            try {
                return Integer.parseInt(str);
            } catch (NumberFormatException e) {
                // 忽略异常，返回默认值
            }
        }
        return defaultValue;
    }

    /**
     * 安全转换为整数（转换失败返回null）
     *
     * @param str 字符串
     * @return 整数
     *
     * @example
     * <pre>{@code
     * Integer result = NumberKit.safeParseInt("123");
     * // 返回 123
     * }</pre>
     */
    public static Integer safeParseInt(String str) {
        return safeParseInt(str, null);
    }

    /**
     * 安全转换为长整数
     *
     * @param str 字符串
     * @param defaultValue 默认值
     * @return 长整数
     *
     * @example
     * <pre>{@code
     * Long result = NumberKit.safeParseLong("123456789", 0L);
     * // 返回 123456789L
     * }</pre>
     */
    public static Long safeParseLong(String str, Long defaultValue) {
        if (str != null && str.matches("-?\\d+")) {
            try {
                return Long.parseLong(str);
            } catch (NumberFormatException e) {
                // 忽略异常，返回默认值
            }
        }
        return defaultValue;
    }

    /**
     * 安全转换为双精度浮点数
     *
     * @param str 字符串
     * @param defaultValue 默认值
     * @return 双精度浮点数
     *
     * @example
     * <pre>{@code
     * Double result = NumberKit.safeParseDouble("123.45", 0.0);
     * // 返回 123.45
     * }</pre>
     */
    public static Double safeParseDouble(String str, Double defaultValue) {
        if (StringKit.isNumericExtended(str)) {
            try {
                return Double.parseDouble(str);
            } catch (NumberFormatException e) {
                // 忽略异常，返回默认值
            }
        }
        return defaultValue;
    }

    /**
     * 安全转换为BigDecimal
     *
     * @param str 字符串
     * @param defaultValue 默认值
     * @return BigDecimal
     *
     * @example
     * <pre>{@code
     * BigDecimal result = NumberKit.safeParseBigDecimal("123.45", BigDecimal.ZERO);
     * // 返回 123.45
     * }</pre>
     */
    public static BigDecimal safeParseBigDecimal(String str, BigDecimal defaultValue) {
        if (StringKit.isNumericExtended(str)) {
            try {
                return new BigDecimal(str);
            } catch (NumberFormatException e) {
                // 忽略异常，返回默认值
            }
        }
        return defaultValue;
    }

    // ========== 数字计算和格式化 ==========

    /**
     * 四舍五入到指定小数位
     *
     * @param number 数字
     * @param scale 小数位数
     * @return 四舍五入后的数字
     *
     * @example
     * <pre>{@code
     * double result = NumberKit.round(123.4567, 2);
     * // 返回 123.46
     * }</pre>
     */
    public static double round(double number, int scale) {
        return BigDecimal.valueOf(number)
                .setScale(scale, RoundingMode.HALF_UP)
                .doubleValue();
    }

    /**
     * 向下取整到指定小数位
     *
     * @param number 数字
     * @param scale 小数位数
     * @return 向下取整后的数字
     *
     * @example
     * <pre>{@code
     * double result = NumberKit.floor(123.4567, 2);
     * // 返回 123.45
     * }</pre>
     */
    public static double floor(double number, int scale) {
        return BigDecimal.valueOf(number)
                .setScale(scale, RoundingMode.FLOOR)
                .doubleValue();
    }

    /**
     * 向上取整到指定小数位
     *
     * @param number 数字
     * @param scale 小数位数
     * @return 向上取整后的数字
     *
     * @example
     * <pre>{@code
     * double result = NumberKit.ceil(123.451, 2);
     * // 返回 123.46
     * }</pre>
     */
    public static double ceil(double number, int scale) {
        return BigDecimal.valueOf(number)
                .setScale(scale, RoundingMode.CEILING)
                .doubleValue();
    }

    /**
     * 格式化数字为货币格式
     *
     * @param number 数字
     * @return 货币格式字符串
     *
     * @example
     * <pre>{@code
     * String result = NumberKit.formatCurrency(1234.56);
     * // 返回 "1,234.56"
     * }</pre>
     */
    public static String formatCurrency(Number number) {
        if (number == null) {
            return "0.00";
        }
        DecimalFormat df = new DecimalFormat("#,##0.00");
        return df.format(number);
    }

    /**
     * 格式化数字为百分比
     *
     * @param number 数字（0-1之间的小数）
     * @param scale 小数位数
     * @return 百分比字符串
     *
     * @example
     * <pre>{@code
     * String result = NumberKit.formatPercent(0.4567, 2);
     * // 返回 "45.67%"
     * }</pre>
     */
    public static String formatPercent(double number, int scale) {
        double percent = number * 100;
        DecimalFormat df = new DecimalFormat("0." + StringKit.repeat("0", scale));
        return df.format(percent) + "%";
    }

    // ========== 随机数生成 ==========

    /**
     * 生成指定范围内的随机整数
     *
     * @param min 最小值（包含）
     * @param max 最大值（包含）
     * @return 随机整数
     *
     * @example
     * <pre>{@code
     * int result = NumberKit.randomInt(1, 100);
     * // 返回 1-100之间的随机整数
     * }</pre>
     */
    public static int randomInt(int min, int max) {
        if (min > max) {
            throw new IllegalArgumentException("最小值不能大于最大值");
        }
        Random random = new Random();
        return random.nextInt(max - min + 1) + min;
    }

    /**
     * 生成指定范围内的随机浮点数
     *
     * @param min 最小值
     * @param max 最大值
     * @param scale 小数位数
     * @return 随机浮点数
     *
     * @example
     * <pre>{@code
     * double result = NumberKit.randomDouble(0.0, 1.0, 2);
     * // 返回 0.00-1.00之间的随机浮点数
     * }</pre>
     */
    public static double randomDouble(double min, double max, int scale) {
        if (min > max) {
            throw new IllegalArgumentException("最小值不能大于最大值");
        }
        Random random = new Random();
        double value = min + (max - min) * random.nextDouble();
        return round(value, scale);
    }

    // ========== 数字比较方法 ==========

    /**
     * 比较两个数字是否相等（考虑精度）
     *
     * @param num1 数字1
     * @param num2 数字2
     * @param precision 精度（小数位数）
     * @return 是否相等
     *
     * @example
     * <pre>{@code
     * boolean result = NumberKit.equals(123.456, 123.457, 2);
     * // 返回 true（因为前两位小数相同）
     * }</pre>
     */
    public static boolean equals(Number num1, Number num2, int precision) {
        if (num1 == null && num2 == null) {
            return true;
        }
        if (num1 == null || num2 == null) {
            return false;
        }
        double d1 = round(num1.doubleValue(), precision);
        double d2 = round(num2.doubleValue(), precision);
        return Double.compare(d1, d2) == 0;
    }

    /**
     * 比较两个数字是否相等（默认6位精度）
     *
     * @param num1 数字1
     * @param num2 数字2
     * @return 是否相等
     *
     * @example
     * <pre>{@code
     * boolean result = NumberKit.equals(123.456, 123.456);
     * // 返回 true
     * }</pre>
     */
    public static boolean equals(Number num1, Number num2) {
        return equals(num1, num2, 6);
    }

    /**
     * 获取数字中的最大值
     *
     * @param numbers 数字数组
     * @return 最大值
     *
     * @example
     * <pre>{@code
     * double result = NumberKit.max(1.0, 2.5, 3.2);
     * // 返回 3.2
     * }</pre>
     */
    public static double max(Number... numbers) {
        if (numbers == null || numbers.length == 0) {
            throw new IllegalArgumentException("数字数组不能为空");
        }
        double max = numbers[0].doubleValue();
        for (int i = 1; i < numbers.length; i++) {
            max = Math.max(max, numbers[i].doubleValue());
        }
        return max;
    }

    /**
     * 获取数字中的最小值
     *
     * @param numbers 数字数组
     * @return 最小值
     *
     * @example
     * <pre>{@code
     * double result = NumberKit.min(1.0, 2.5, 3.2);
     * // 返回 1.0
     * }</pre>
     */
    public static double min(Number... numbers) {
        if (numbers == null || numbers.length == 0) {
            throw new IllegalArgumentException("数字数组不能为空");
        }
        double min = numbers[0].doubleValue();
        for (int i = 1; i < numbers.length; i++) {
            min = Math.min(min, numbers[i].doubleValue());
        }
        return min;
    }

    // ========== 数值计算 ==========

    /**
     * 计算百分比
     *
     * @param part 部分值
     * @param total 总值
     * @param scale 小数位数
     * @return 百分比数值（0-100）
     *
     * @example
     * <pre>{@code
     * double result = NumberKit.calculatePercentage(25, 100, 2);
     * // 返回 25.00
     * }</pre>
     */
    public static double calculatePercentage(double part, double total, int scale) {
        if (total == 0) {
            return 0;
        }
        double percentage = (part / total) * 100;
        return round(percentage, scale);
    }

    /**
     * 计算增长率
     *
     * @param current 当前值
     * @param previous 之前值
     * @param scale 小数位数
     * @return 增长率百分比
     *
     * @example
     * <pre>{@code
     * double result = NumberKit.calculateGrowthRate(150, 100, 2);
     * // 返回 50.00
     * }</pre>
     */
    public static double calculateGrowthRate(double current, double previous, int scale) {
        if (previous == 0) {
            return current > 0 ? 100 : 0;
        }
        double growthRate = ((current - previous) / previous) * 100;
        return round(growthRate, scale);
    }
}